package com.hanxiaozhang.validation.validator;



import com.hanxiaozhang.validation.annotation.EnumRange;


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 〈一句话功能简述〉<br>
 * 〈枚举类范围校验器〉
 *
 * @author hanxinghua
 * @create 2020/7/20
 * @since 1.0.0
 */
public class EnumRangeValidator implements ConstraintValidator<EnumRange, Object> {

    private Class<? extends Enum<?>> enumClass;
    private String enumValidMethod;

    @Override
    public void initialize(EnumRange enumRange) {
        enumClass = enumRange.enumClass();
        enumValidMethod = enumRange.enumValidMethod();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
        if (value == null) {
            return true;
        }

        if (enumClass == null || enumValidMethod == null) {
            return true;
        }

        Class<?> valueClass = value.getClass();

        try {
            // 反射获取方法
            Method method = enumClass.getMethod(enumValidMethod, valueClass);
            // 校验 enumValidMethod 是否为 boolean类型方法
            if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) {
                throw new RuntimeException(String.format("%s method return is not boolean type in the %s class", enumValidMethod, enumClass));
            }
            // 校验 enumValidMethod 是否为 静态类型方法
            if(!Modifier.isStatic(method.getModifiers())) {
                throw new RuntimeException(String.format("%s method is not static method in the %s class", enumValidMethod, enumClass));
            }
            // 反射调用该方法
            Boolean result = (Boolean)method.invoke(null, value);
            
            return result == null ? false : result;
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException | SecurityException e) {
            throw new RuntimeException(String.format("This %s(%s) method does not exist in the %s", enumValidMethod, valueClass, enumClass), e);
        }
    }


}
